home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
aminet
/
gfx
/
misc
/
dctvdev3.lzh
/
example
/
graygrad.c
< prev
Wrap
C/C++ Source or Header
|
1992-08-12
|
16KB
|
511 lines
/**********************************************************************
*
* graygrad.c - Convert DCTV gradient to 4-bit gray screen.
*
* Copyright (C) 1992 Digital Creations, Inc.
*
* DESCRIPTION
* This example demonstrates how to call dctv.library to convert
* a DCTV display BitMap to 24-bit RGB. The source DCTV BitMap
* is a gradient generated in the same manner as in dctvgrad.c.
* This DCTV image is then converted line by line to 24-bit RGB.
* Then the upper 4 bits of the blue component are displayed on
* a 16-color hires screen.
*
* (not particularly flashy, but at least you get to see something).
*
* Program runs under Amiga OS v1.3 and higher.
*
* USAGE
* graygrad <width> <height> <depth>
* width - screen width (640..736)
* height - screen height (200..241, 400..482)
* depth - screen depth (3..4)
*
* Terminate with Control+C.
*
* COMPILATION
* SAS/C: (v5.10 or higher. Regular of ANSI libs)
* lc -L+dctv.lib graygrad
*
* Aztec C: (v5.0a or higher)
* cc graygrad [works w/ either 16 or 32 bit int's]
* ln graygrad.o +l dctv.lib -lc
*
* REQUIREMENTS
* . Aztec C 5.0 or SAS/C 5.10.
* . v37.4 or higher Amiga include files.
* . OS #pragmas created for your compiler in the pragmas
* directory of your include path.
*
**********************************************************************/
#include <dos/dos.h>
#include <exec/memory.h>
#include <intuition/screens.h>
#include <libraries/dctv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <clib/dctv_protos.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <pragmas/dctv_pragmas.h>
#include <pragmas/exec_pragmas.h>
#include <pragmas/graphics_pragmas.h>
#include <pragmas/intuition_pragmas.h>
/* -------------------- misc defines */
#define DCTVLIB_Version 3
#define READPIXEL 0 /* selects DCTV->RGB conversion method: set to 1 to use ReadDCTVPixel(), 0 to use CvtDCTVLine() */
#define LaceHeight(height) (height > 350)
/* -------------------- data */
struct Library *DCTVBase, *GfxBase, *IntuitionBase;
/* -------------------- local functions */
void dograd (short width, short height, short depth);
BOOL makedctvbm (struct BitMap *dctvbm, UWORD *palette, short width, short height);
void showgrad (struct BitMap *dctvbm, UWORD *palette, short width, short height);
/* bitmap allocator */
struct BitMap *allocbm (UWORD width, UWORD height, UBYTE depth);
void freebm (struct BitMap *);
/* gradient functions */
void initgrad (struct DCTVCvtHandle *);
void rendergradline (struct DCTVCvtHandle *);
/* -------------------- main() */
#if AZTEC_C
void _wb_parse (void) {} /* stub out wb window parser */
#endif
#if __SASC /* suppress normal Ctrl-C processing (SAS/C) */
void __chkabort (void) {}
void chkabort (void) {}
#endif
int main (int argc, char **argv)
{
if (argc < 4) goto clean;
#if AZTEC_C /* suppress normal Ctrl-C processing (Aztec C) */
{
extern int Enable_Abort;
Enable_Abort = 0;
}
#endif
if (!(IntuitionBase = OpenLibrary ("intuition.library", LIBRARY_MINIMUM))) goto clean;
if (!(GfxBase = OpenLibrary ("graphics.library", LIBRARY_MINIMUM))) goto clean;
if (!(DCTVBase = OpenLibrary ("dctv.library", DCTVLIB_Version))) {
printf ("requires dctv.library v%d\n", DCTVLIB_Version);
goto clean;
}
dograd (atoi(argv[1]), atoi(argv[2]), atoi(argv[3]));
clean:
if (DCTVBase) CloseLibrary (DCTVBase);
if (GfxBase) CloseLibrary (GfxBase);
if (IntuitionBase) CloseLibrary (IntuitionBase);
return 0;
}
/* -------------------- dograd() */
void dograd (short width, short height, short depth)
{
struct BitMap *dctvbm = NULL;
UWORD *palette = NULL;
/* pad width to next multiple of 16 */
width = width + 15 & ~15;
/* allocate a bitmap and palette to hold DCTV display image.
Notice that this BitMap is not allocated in chip ram as the
conversions don't require the bitmap to be displayable. */
if (!(dctvbm = allocbm (width, height, depth)) ||
!(palette = AllocMem (sizeof (UWORD) << depth, MEMF_ANY | MEMF_CLEAR))) {
puts ("Out of memory\n");
goto clean;
}
/* build DCTV bitmap (draw same gradient as dctvgrad.c) */
if (!makedctvbm (dctvbm, palette, width, height)) goto clean;
/* convert DCTV display image to a 16-color gray screen of the
same size as the BitMap */
showgrad (dctvbm, palette, width, height);
clean:
if (palette) FreeMem (palette, sizeof (UWORD) << depth);
if (dctvbm) freebm (dctvbm);
}
/* -------------------- DCTV gradient bitmap builder */
/* this part is pretty much the same as in dctvgrad.c */
BOOL makedctvbm (struct BitMap *dctvbm, UWORD *palette, short width, short height)
{
struct DCTVCvtHandle *cvt = NULL;
ULONG errcode;
BOOL rtn = FALSE;
puts ("Making gradient.");
/* Allocate DCTV conversion environment. */
if (!(cvt = AllocDCTVCvtTags ( dctvbm,
DCTVCVTA_Type, (ULONG)DCTVCVTT_RGBtoDCTV,
DCTVCVTA_Width, (ULONG)width,
DCTVCVTA_Height, (ULONG)height,
DCTVCVTA_Flags, (ULONG)(LaceHeight(height) ? DCTVCVTF_Lace : 0),
DCTVCVTA_ErrorCode, &errcode,
TAG_END ))) {
printf ("AllocDCTVCvtTags failed %lu\n", errcode);
goto clean;
}
/* copy ColorTable to palette */
CopyMem (cvt->ColorTable, palette, cvt->NColors * sizeof (UWORD));
/* initialize gradient */
initgrad (cvt); /* Init gradient data. */
/* Line rendering loop. (See dctvgrad.c for a more complete explanation of this) */
while (cvt->DstLineNum < cvt->Height) {
/* Abort on Ctrl-C. */
if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) goto clean;
rendergradline (cvt); /* Render a line of the gradient to
DCTVCvtHandle RGB line buffer.
This function is smart enough to
handle line #'s out of range. */
CvtDCTVLine (cvt); /* Convert the line in the line buffer to
DCTV display data. Results in rendering
a line of the BitMap. */
}
rtn = TRUE;
clean:
if (cvt) FreeDCTVCvt (cvt);
return rtn;
}
/* -------------------- gray gradient display */
struct Screen *openscreen (short width, short height);
BOOL rendergrayscreen (struct Screen *, struct DCTVCvtHandle *);
void showgrad (struct BitMap *dctvbm, UWORD *palette, short width, short height)
{
struct Screen *screen = NULL;
struct DCTVCvtHandle *cvt = NULL;
ULONG errcode;
puts ("Building Screen.");
if (!(screen = openscreen (width, height))) {
puts ("openscreen() failed\n");
goto clean;
}
if (!(cvt = AllocDCTVCvtTags ( dctvbm,
DCTVCVTA_Type, (ULONG)DCTVCVTT_DCTVtoRGB,
DCTVCVTA_Width, (ULONG)width,
DCTVCVTA_Height, (ULONG)height,
DCTVCVTA_Flags, (ULONG)(LaceHeight(height) ? DCTVCVTF_Lace : 0),
DCTVCVTA_ColorTable, palette,
DCTVCVTA_ErrorCode, &errcode,
TAG_END ))) {
printf ("AllocDCTVCvtTags() failed %lu\n", errcode);
goto clean;
}
if (!rendergrayscreen (screen, cvt)) goto clean;
puts ("Press Ctrl-C");
Wait (SIGBREAKF_CTRL_C);
clean:
if (cvt) FreeDCTVCvt (cvt);
if (screen) CloseScreen (screen);
}
struct Screen *openscreen (short width, short height)
{
static struct NewScreen newscreen = {
0, 0, 0, 0, 4,
-1, -1,
0,
CUSTOMSCREEN | SCREENQUIET,
NULL,
"graygrad",
NULL,
NULL
};
static UWORD palette[] = { /* gray palette */
0x000, 0x111, 0x222, 0x333,
0x444, 0x555, 0x666, 0x777,
0x888, 0x999, 0xaaa, 0xbbb,
0xccc, 0xddd, 0xeee, 0xfff
};
struct Screen *screen;
newscreen.Width = width;
newscreen.Height = height;
newscreen.ViewModes = LaceHeight(height) ? HIRESLACE_KEY : HIRES_KEY;
if (screen = OpenScreen (&newscreen)) {
LoadRGB4 (&screen->ViewPort, palette, 16);
}
return screen;
}
#if READPIXEL
/* display gradient using ReadDCTVPixel() */
BOOL rendergrayscreen (struct Screen *screen, struct DCTVCvtHandle *cvt)
{
struct RastPort *rp = &screen->RastPort;
short x, y;
/* !!! fix docs! */
/*
Line rendering loop.
Loop until all Destination lines have been converted
(indicated by DstLineNum >= height).
Because the conversion process may introduce an N-line delay
between source and destination lines, you must call
CvtDCTVLine() until all the destination lines have been
converted. That means the code in this loop will be
executed (height + NDelayLines) times.
Your rendering RGB processing code should use DstLineNum-1
after converting each line to figure out which RGB line was
just made.
Since the range of DstLineNum is
-NDelayLines < DstLineNum <= Height after each call, you need
to make sure that CvtDCTVLine() actually output a line for you
to use. If DstLineNum is in the range of
0 < DstLineNum <= Height after calling CvtDCTVLine() then a
line of RGB was just emitted.
*/
/*
Convert the current line in the RGB line buffer to 4-bit gray by
extracting just the upper 4 bits of the Blue component.
The caller of this function is expected to avoid calling it for
DstLineNum values out of range.
The line being displayed is DstLineNum-1 (DstLineNum indicates the
_next_ line to be output by CvtDCTVLine()).
NOTE: this loop is pathetically slow (mainly due to WritePixel()),
but is sufficient for this example.
*/
SetDrMd (rp, JAM1);
for (x = 0; x < screen->Width; x++) {
/* Abort on Ctrl-C. */
if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) return FALSE;
for (y = 0; y < screen->Height; y++) {
SetAPen (rp, (ReadDCTVPixel (cvt, x, y) & 0xf0) >> 4); /* get upper 4 bits of blue */
WritePixel (rp, x, y);
}
}
return TRUE;
}
#else
/* display gradient using CvtDCTVLine() */
void rendergrayline (struct RastPort *, struct DCTVCvtHandle *);
BOOL rendergrayscreen (struct Screen *screen, struct DCTVCvtHandle *cvt)
{
/*
Line rendering loop.
Loop until all Destination lines have been converted
(indicated by DstLineNum >= height).
Because the conversion process may introduce an N-line delay
between source and destination lines, you must call
CvtDCTVLine() until all the destination lines have been
converted. That means the code in this loop will be
executed (height + NDelayLines) times.
Your rendering RGB processing code should use DstLineNum-1
after converting each line to figure out which RGB line was
just made.
Since the range of DstLineNum is
-NDelayLines < DstLineNum <= Height after each call, you need
to make sure that CvtDCTVLine() actually output a line for you
to use. If DstLineNum is in the range of
0 < DstLineNum <= Height after calling CvtDCTVLine() then a
line of RGB was just emitted.
*/
while (cvt->DstLineNum < cvt->Height) {
/* Abort on Ctrl-C. */
if (SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C) return FALSE;
CvtDCTVLine (cvt); /* Convert the line in the line buffer to
DCTV display data. Results in rendering
a line of the BitMap. */
/* Display 4-bit gray from 24-bit RGB.
This draws directly to the Screen's Rastport. */
if (cvt->DstLineNum > 0)
rendergrayline (&screen->RastPort, cvt);
}
return TRUE;
}
void rendergrayline (struct RastPort *rp, struct DCTVCvtHandle *cvt)
{
short x;
short y = cvt->DstLineNum - 1; /* after call, subtract 1 for line just emitted */
/*
Convert the current line in the RGB line buffer to 4-bit gray by
extracting just the upper 4 bits of the Blue component.
The caller of this function is expected to avoid calling it for
DstLineNum values out of range.
The line being displayed is DstLineNum-1 (DstLineNum indicates the
_next_ line to be output by CvtDCTVLine()).
NOTE: this loop is pathetically slow (mainly due to WritePixel()),
but is sufficient for this example.
*/
SetDrMd (rp, JAM1);
for (x = 0; x < cvt->Width; x++) {
SetAPen (rp, cvt->Blue[x] >> 4);
WritePixel (rp, x, y);
}
}
#endif
/* -------------------- bitmap allocator */
struct BitMap *allocbm (UWORD width, UWORD height, UBYTE depth)
{
ULONG memsize;
PLANEPTR *ras;
struct BitMap *bm;
if (depth > 8) goto clean;
if (!(bm = AllocMem (sizeof *bm, MEMF_ANY | MEMF_CLEAR))) goto clean;
InitBitMap (bm, depth, width, height);
memsize = (ULONG)bm->Rows * bm->BytesPerRow;
for (ras=bm->Planes; depth--;) {
if (!(*ras++ = AllocMem (memsize, MEMF_ANY | MEMF_CLEAR))) goto clean;
}
return bm;
clean:
if (bm) freebm (bm);
return NULL;
}
void freebm (struct BitMap *bm)
{
ULONG rassize = (ULONG)bm->Rows * bm->BytesPerRow;
PLANEPTR *ras;
short i;
for (ras = bm->Planes, i = bm->Depth; i--; ras++) {
if (*ras) {
FreeMem (*ras, rassize);
*ras = NULL;
}
}
FreeMem (bm, sizeof *bm);
}
/* -------------------- 24-bit RGB gradient functions */
#define gcent(m,l) (((m)-(l)) / 2) /* centering macro */
void initgrad (struct DCTVCvtHandle *cvt)
{
short bufwidth = cvt->Width;
short imagewidth = cvt->ImageBounds.MaxX - cvt->ImageBounds.MinX + 1;
short i;
/* init line to black */
memset (cvt->Red, 0, bufwidth);
memset (cvt->Green, 0, bufwidth);
memset (cvt->Blue, 0, bufwidth);
/* ramp red horizontally */
for (i=0; i < imagewidth; i++)
cvt->Red [i+cvt->ImageBounds.MinX] = (ULONG)i * 255 / imagewidth;
}
void rendergradline (struct DCTVCvtHandle *cvt)
{
short imagewidth = cvt->ImageBounds.MaxX - cvt->ImageBounds.MinX + 1;
short imageheight = cvt->ImageBounds.MaxY - cvt->ImageBounds.MinY + 1;
short y = cvt->SrcLineNum - cvt->ImageBounds.MinY;
short bluewidth;
UBYTE greenval;
if (y >= 0 && y < imageheight) {
/* constant green component for line */
greenval = (long)y * 255 / imageheight;
memset (cvt->Green + cvt->ImageBounds.MinX, greenval, imagewidth);
/* reverse wedge blue component */
bluewidth = (long)(imageheight - y) * imagewidth / imageheight;
if (bluewidth > 0)
memset (cvt->Blue + gcent (imagewidth, bluewidth) + cvt->ImageBounds.MinX, 255-greenval, bluewidth);
}
}